home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
KSUBR.C
< prev
next >
Wrap
Text File
|
1993-11-17
|
6KB
|
255 lines
/* Machine or compiler-dependent portions of kernel
* Turbo-C version for PC
*
* Copyright 1991 Phil Karn, KA9Q
*/
#include <stdio.h>
#include <dos.h>
#include "global.h"
#include "proc.h"
#include "pc.h"
#include "commands.h"
static int near chkintstk __ARGS((void));
#undef PROCLOG
#ifdef PROCLOG
int stkutil __ARGS((struct proc *pp));
#else
static int near stkutil __ARGS((struct proc *pp));
#endif
/* Template for contents of jmp_buf in Turbo C */
struct env {
unsigned sp;
unsigned ss;
unsigned flag;
unsigned cs;
unsigned ip;
unsigned bp;
unsigned di;
unsigned es;
unsigned si;
unsigned ds;
};
void
kinit(void)
{
int i;
/* Initialize interrupt stack for high-water-mark checking */
for(i = 0; i < 512; i++)
Intstk[i] = STACKPAT;
}
/* Print process table info
* Since things can change while ps is running, the ready proceses are
* displayed last. This is because an interrupt can make a process ready,
* but a ready process won't spontaneously become unready. Therefore a
* process that changes during ps may show up twice, but this is better
* than not having it showing up at all.
*/
int
ps(int argc,char **argv,void *p)
{
struct proc *pp;
struct env *ep;
char *Taskers[] = {
"",
"DoubleDos",
"DesqView",
"Windows3",
"OS/2",
};
tprintf("Stack %x max intstk %u",getss(),chkintstk());
if(Mtasker != 0)
tprintf(" Running under %s",Taskers[Mtasker]);
tputs("\nPID SP size max event fl in out name\n");
for(pp = Susptab; pp != NULLPROC; pp = pp->next) {
ep = (struct env *)&pp->env;
tprintf("%-5lx%-5lx%-6u%-6u%-7lx%c%c%c %d %d %s\n",
ptol(pp),
ptol((void *)MK_FP(ep->ss,ep->sp)),
pp->stksize,
stkutil(pp),
ptol(pp->event),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input, pp->output,
pp->name);
}
for(pp = Waittab; pp != NULLPROC; pp = pp->next) {
ep = (struct env *)&pp->env;
tprintf("%-5lx%-5lx%-6u%-6u%-7lx%c%c%c %d %d %s\n",
ptol(pp),
ptol((void *)MK_FP(ep->ss,ep->sp)),
pp->stksize,
stkutil(pp),
ptol(pp->event),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input,
pp->output,
pp->name);
}
for(pp = Rdytab; pp != NULLPROC; pp = pp->next) {
ep = (struct env *)&pp->env;
tprintf("%-5lx%-5lx%-6u%-6u %c%c%c %d %d %s\n",
ptol(pp),
ptol((void *)MK_FP(ep->ss,ep->sp)),
pp->stksize,
stkutil(pp),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input,
pp->output,
pp->name);
}
if(Curproc != NULLPROC) {
ep = (struct env *)&Curproc->env;
tprintf("%-5lx%-5lx%-6u%-6u %c %d %d %s\n",
ptol(Curproc),
ptol((void *)MK_FP(ep->ss,ep->sp)),
Curproc->stksize,
stkutil(Curproc),
Curproc->i_state ? 'I' : ' ',
Curproc->input,
Curproc->output,
Curproc->name);
}
return 0;
}
#ifdef PROCLOG
int
#else
static int near
#endif
stkutil(struct proc *pp)
{
int16 *sp = pp->stack;
unsigned int i = pp->stksize;
for( ; *sp == STACKPAT && sp < (pp->stack + pp->stksize); sp++) {
i--;
}
return (int)i;
}
/* Return number of used words in interrupt stack. Note hardwired value
* for stack size; this is also found in the various .asm files
*/
static int near
chkintstk(void)
{
int i = 512;
int16 *cp = Intstk;
for( ; i != 0 && *cp == STACKPAT; cp++) {
i--;
}
return i;
}
#ifdef MDEBUG
/* Verify that stack pointer for current process is within legal limits;
* also check that no one has dereferenced a null pointer
*/
void
chkstk(void)
{
struct proc *Curproct = Curproc;
int16 *sbase, *stop, *sp = (int16 *)(MK_FP(_SS,_SP));
if(_SS == _DS) {
/* Probably in interrupt context */
return;
}
if((sbase = Curproct->stack) == NULL) {
/* Main task -- too hard to check */
return;
}
stop = sbase + Curproct->stksize;
if(sp < sbase || sp >= stop) {
dirps();
iostop();
printf("\nStack violation, process %s\n",Curproct->name);
#ifdef MDEBUG
printf("SP=%lx, legal stack range [%lx,%lx] ",
ptol(sp),ptol(sbase),ptol(stop));
#endif
printf("stksize=%u, maxstk=%u\n\n",Curproct->stksize,stkutil(Curproct));
exit(254);
}
}
#endif
/* Machine-dependent initialization of a task */
void
psetup(
struct proc *pp, /* Pointer to task structure */
int iarg, /* Generic integer arg */
void *parg1, /* Generic pointer arg #1 */
void *parg2, /* Generic pointer arg #2 */
void (*pc)()) /* Initial execution address */
{
struct env *ep;
/* Set up stack to make it appear as if the user's function was called
* by killself() with the specified arguments. When the user returns,
* killself() automatically cleans up.
*
* First, push args on stack in reverse order, simulating what C
* does just before it calls a function.
*/
unsigned *stktop = ((unsigned *)pp->stack + pp->stksize);
#ifdef LARGEDATA
*--stktop = FP_SEG(parg2);
#endif
*--stktop = FP_OFF(parg2);
#ifdef LARGEDATA
*--stktop = FP_SEG(parg1);
#endif
*--stktop = FP_OFF(parg1);
*--stktop = iarg;
/* Now push the entry address of killself(), simulating the call to
* the user function.
*/
#ifdef LARGECODE
*--stktop = FP_SEG(killself);
#endif
*--stktop = FP_OFF(killself);
/* Set up task environment. Note that for Turbo-C, the setjmp
* sets the interrupt enable flag in the environment so that
* interrupts will be enabled when the task runs for the first time.
* Note that this requires newproc() to be called with interrupts
* enabled!
*/
setjmp(pp->env);
ep = (struct env *)&pp->env;
ep->ss = FP_SEG(stktop);
ep->sp = FP_OFF(stktop);
ep->cs = FP_SEG(pc); /* Doesn't hurt in small model */
ep->ip = FP_OFF(pc);
/* Task initially runs with interrupts on */
pp->i_state = 1;
}